package com.tiancheng.trade.commom.core.utils;

import cn.hutool.core.map.MapUtil;
import com.dtflys.forest.Forest;
import com.dtflys.forest.config.ForestConfiguration;
import com.dtflys.forest.http.ForestRequest;
import com.dtflys.forest.http.ForestRequestType;
import com.tiancheng.trade.commom.core.exception.PlatformServiceCallException;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.message.BasicHeader;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @Author: kellen
 * @Description:
 * @Date: create in 2024/11/21 11:16
 */
public class ForestHttpUtil {
    private static ForestConfiguration configuration;
    private static ForestHttpUtil httpUtils;

    private ForestHttpUtil() {
    }

    public static synchronized ForestHttpUtil getInstance() {
        if (httpUtils == null) {
            httpUtils = new ForestHttpUtil();
            initialize();
        }
        return httpUtils;
    }

    private static void initialize() {
        configuration = Forest.config();
        // 连接池最大连接数
        configuration.setMaxConnections(1000);
        // 连接超时时间，单位为毫秒
        configuration.setConnectTimeout(3000);
        // 数据读取超时时间，单位为毫秒
        configuration.setReadTimeout(6000);
    }


    /**
     * http post signature方式
     *
     * @param url
     * @param bodyParam 参数
     * @param headers   请求头
     * @return
     * @throws Throwable
     */
    public String doPostJson(String url, Object bodyParam, Header... headers) {
        ForestRequest<?> request = configuration.request();
        request.url(url);
        request.setType(ForestRequestType.POST);
        if (headers == null) {
            headers = new BasicHeader[]{new BasicHeader("content-type", "application/json")};
        }
        setHeader(request, headers);
        setParams(request, null, bodyParam, false);
        AtomicReference<String> result = new AtomicReference<>();
        request.onSuccess((data, forestRequest, forestResponse) -> {
            result.set(JsonUtil.toJsonString(data));
        });
        request.onError((ex, forestRequest, forestResponse) -> {
            throw new PlatformServiceCallException("请求异常:" + ex.getMessage());
        });
        request.execute();
        return result.get();
    }


    /**
     * http post signature方式
     *
     * @param url
     * @param bodyParam 参数
     * @param headers   请求头
     * @return
     * @throws Throwable
     */
    public String doPost(String url, Object bodyParam, Header... headers) {
        ForestRequest<?> request = configuration.request();
        request.url(url);
        request.setType(ForestRequestType.POST);
        request.setReadTimeout(10000);//毫秒
        setHeader(request, headers);
        setParams(request, null, bodyParam, true);
        AtomicReference<String> result = new AtomicReference<>();
        request.onSuccess((data, forestRequest, forestResponse) -> {
            result.set(JsonUtil.toJsonString(data));
        });
        request.onError((ex, forestRequest, forestResponse) -> {
            throw new PlatformServiceCallException("请求异常:" + ex.getMessage());
        });
        request.execute();
        return result.get();
    }

    /**
     * http post signature方式
     *
     * @param url
     * @param params  参数
     * @param headers 请求头
     * @return
     * @throws Throwable
     */
    public String doPostForm(String url, Map<String, Object> params, Header... headers) {
        ForestRequest<?> request = configuration.request();
        request.url(url);
        request.setType(ForestRequestType.POST);
        if (headers == null) {
            headers = new BasicHeader[]{new BasicHeader("content-type", "application/x-www-form-urlencoded")};
        }
        setHeader(request, headers);
        request.addBody(params);
        AtomicReference<String> result = new AtomicReference<>();
        request.onSuccess((data, forestRequest, forestResponse) -> {
            result.set(JsonUtil.toJsonString(data));
        });
        request.onError((ex, forestRequest, forestResponse) -> {
            throw new PlatformServiceCallException("请求异常:" + ex.getMessage());
        });
        request.execute();
        return result.get();
    }
    /**
     * http post signature方式
     *
     * @param url
     * @param file    参数
     * @param headers 请求头
     * @return
     * @throws Throwable
     */
    public String multipartForm(String url, MultipartFile file, Map<String, Object> params, Header... headers) {
        ForestRequest<?> request = configuration.request();
        request.url(url);
        request.setType(ForestRequestType.POST);
        request.contentTypeMultipartFormData();
        request.setReadTimeout(10 * 1000);
        request.connectTimeout(5 * 1000);
        if (null != params && params.size() > 0) {
            request.addQuery(params);
        }
        setHeader(request, headers);
        try {
            request.addFile("file", file.getInputStream(), file.getOriginalFilename());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        AtomicReference<String> result = new AtomicReference<>();
        request.onSuccess((data, forestRequest, forestResponse) -> {
            result.set(JsonUtil.toJsonString(data));
        });
        request.onError((ex, forestRequest, forestResponse) -> {
            throw new PlatformServiceCallException("上传文件异常:" + ex.getMessage());
        });
        request.execute();
        return result.get();
    }


    private void setParams(ForestRequest<?> request, Map<String, Object> urlParams, Object bodyParam, boolean useFormData) {
        if (MapUtil.isNotEmpty(urlParams)) {
            request.addQuery(urlParams);
        }
        if (Objects.nonNull(bodyParam)) {
            if (useFormData) {
                final Map<String, Object> params = new HashMap<>();
                for (Field field : bodyParam.getClass().getDeclaredFields()) {
                    try {
                        field.setAccessible(true);
                        // 属性值为null或空串，不收集
                        if (null == field.get(bodyParam) || StringUtils.isBlank(field.get(bodyParam).toString()))
                            continue;
                        params.put(field.getName(), field.get(bodyParam));
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
                request.addQuery(params, false, "utf-8");
            } else {
                request.addBody(bodyParam);
            }
        }
    }

    /**
     * 设置请求头
     *
     * @param request
     * @param headers
     */
    private void setHeader(ForestRequest<?> request, Header... headers) {
        if (null != headers) {
            for (Header header : headers) {
                request.addHeader(header.getName(), header.getValue());
            }
        }
    }
}
